package cn.com.hatech.cdkey.config.mvc;


import cn.com.hatech.cdkey.common.constant.ErrorCode;
import cn.com.hatech.cdkey.common.exception.TipException;
import cn.com.hatech.cdkey.common.interceptor.BaseInterceptor;
import cn.com.hatech.cdkey.common.result.RestResponse;
import cn.com.hatech.cdkey.config.upload.UploadConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @projectName: hatech-blog
 * @package: cn.com.hatech.blog.config.mvc
 * @className: WebMvcConfig
 * @author: xuruikai
 * @description: WebMvcConfig 公共配置
 * @date: 2020/1/11 14:27
 * @version: 1.0
 */
@Component
@Slf4j
public class WebMvcConfig extends WebMvcConfigurationSupport {
    /**
     * 公共拦截器
     */
    @Resource
    private BaseInterceptor baseInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(baseInterceptor)
                .excludePathPatterns("/", "/login.html", "/user/login", "/**/*.css", "/**/*.js", "/**/*.png",
                        "/**/*.jpg", "/**/*.jpeg", "/**/*.gif", "/**/fonts/*", "/**/*.svg");
    }

    /**
     * 添加静态资源文件，外部可以直接访问地址
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 文件静态资源访问路径
        registry.addResourceHandler("/profile/**").addResourceLocations("file:" + UploadConfig.getUploadPath());
        // 静态文件 js css ... 路径
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        super.addResourceHandlers(registry);
    }

    /**
     * 异常配置
     *
     * @param exceptionResolvers
     */
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
        exceptionResolvers.add(getHandlerExceptionResolver());
    }

    /**
     * 创建异常处理
     *
     * @return
     */
    private HandlerExceptionResolver getHandlerExceptionResolver() {
        return (request, response, handler, e) -> {
            RestResponse<Object> result = getResultByHandleException(request, handler, e);
            responseResult(response, result);
            return new ModelAndView();
        };
    }

    /**
     * 根据异常类型确定返回数据
     *
     * @param request
     * @param handler
     * @param e
     * @return
     */
    private RestResponse<Object> getResultByHandleException(HttpServletRequest request, Object handler, Exception e) {
        RestResponse<Object> result = new RestResponse<>();
        if (e instanceof NoHandlerFoundException) {
            return RestResponse.fail(ErrorCode.NOT_FOUND, "接口 [" + request.getRequestURI() + "] 不存在");
        }
        if (e instanceof TipException) {
            TipException tipException = (TipException) e;
            return RestResponse.fail(tipException.getCode(), tipException.getMessage());
        }
        String message;
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            message = String.format("接口 [%s] 出现异常，方法：%s.%s，异常摘要：%s", request.getRequestURI(), handlerMethod.getBean().getClass().getName(), handlerMethod.getMethod().getName(), e.getMessage());
        } else {
            message = e.getMessage();
        }
        log.error(message, e);
        return result;
    }

    /**
     * @param response
     * @param result
     * @Title: responseResult
     * @Description: 响应结果
     * @Reutrn void
     */
    private void responseResult(HttpServletResponse response, RestResponse<Object> result) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        response.setStatus(200);
        try {
            response.getWriter().write(JSON.toJSONString(result, SerializerFeature.WriteMapNullValue));
        } catch (IOException ex) {
            log.error(ex.getMessage());
        }
    }
}
